package com.itheima.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.SetmealDto;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Setmeal;
import com.itheima.reggie.entity.SetmealDish;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.SetmealService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/setmeal")
public class SetmealController {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SetmealService setmealService;

    /**
     * 新增套餐
     * @param setmealDto 套餐信息，里面还有 setmealDish 套餐菜品信息
     * @return
     */
    @PostMapping
    @CacheEvict(value = "setmealCache",allEntries = true) //清除setmealCache名称下,所有的缓存数据
    public R<String> save(@RequestBody SetmealDto setmealDto){
        //输出调试日志
        log.info("新增套餐功能……");

        //执行自定义的方法的 sql 语句，保存套餐以及菜品信息
        setmealService.saveWithDish(setmealDto);

        //返回结果提示前端
        return R.success("新增套餐成功");
    }

    /**
     * 套餐管理页面得数据显示
     * @param page  第几页
     * @param pageSize 每一页显示条数
     * @param name  模糊搜索字段
     * @return
     */
    @GetMapping("/page")
    public R<Page> page(int page,int pageSize,String name){
        //输出调试日志
        log.info("套餐管理页面数据显示,搜索：{}",name);

        //1.构造分页构造器
        Page<Setmeal> setmealPage = new Page<>(page,pageSize);
        Page<SetmealDto> setmealDtoPage = new Page<>(page,pageSize);

        //2.创建条件构造器
        //这里泛型只要 setmeal 就行，因为我们不用 setmeal套餐得数据，这里也没有传送它得数据，我们只需要通过 lambda 获取字段就可以
        LambdaQueryWrapper<Setmeal> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //创建条件进行模糊查询
        lambdaQueryWrapper.like(name != null,Setmeal::getName,name);//根据套餐名字模糊查询
        //模糊查询之后，进行排序
        lambdaQueryWrapper.orderByDesc(Setmeal::getUpdateTime);

        //3.执行 sql 语句进行查询 套餐setmeal 表得相关信息
        setmealService.page(setmealPage,lambdaQueryWrapper);

        //将 setmealPage 得所有得属性转移到 setmealDtoPage 上面去（因为页面需要 Dto 里面得分类名称 categoryName 字段，setmeal没有）
        BeanUtils.copyProperties(setmealPage,setmealDtoPage);

        //通过 stream 流进行给字段 分类名称categoryName 进行赋值
        // 因为page对象页面数据传送得是 records ，所以我们通过records获取 categoryId 才行
        List<SetmealDto> setmealDtoList = setmealPage.getRecords().stream().map((item) -> {
            //创建 Dto 对象
            SetmealDto setmealDto = new SetmealDto();
            //进行给 dto 对象转移属性,将 item（records 里面的元素对象全部转移到 dto 的 list集合）
            BeanUtils.copyProperties(item, setmealDto);
            //将分类id查询
            Long categoryId = item.getCategoryId();
            //将套餐分类名查询出来
            Category category = categoryService.getById(categoryId);
            //进行判断 category 是否为 null
            if (category != null){
                //再获取 套餐分类 名字
                String categoryName = category.getName();
                //设置套餐分类的名字
                setmealDto.setCategoryName(categoryName);
            }

            //返回 Dto 对象，里面有 setmealDishList套餐菜品表信息，也有 setmeal套餐 信息，还有 还有 categoryName 套餐分类名信息
            return setmealDto;
        }).collect(Collectors.toList());

        //将 查询出来的 dto 集合添加到 setmealDtoPage 的records属性里面
        setmealDtoPage.setRecords(setmealDtoList);

        //返回数据到前端，现在就可以显示 categoryName
        return R.success(setmealDtoPage);
    }


    /**
     * 套餐管理的删除功能，连同 关系表setmeal_dish 也进行删除了
     * @param ids 需要删除的套餐的id,
     *            因为是 List 集合，所以必须使用 @RequestParam 声明，不然 spring会去创建 List 这个类，找不到
     * @return
     */
    @DeleteMapping
    @CacheEvict(value = "setmealCache",allEntries = true) //清除setmealCache名称下,所有的缓存数据
    public R<String> delete(@RequestParam List<Long> ids){
        //输出调试日志
        log.info("批量删除套餐功能，ids：{}",ids);

        //执行之定义的删除功能
        setmealService.removeWithDish(ids);

        //返回 msg 到前端
        return R.success("删除成功！");
    }


    /**
     * 移动端显示套餐数据
     * @param setmeal  捕获封装 移动端访问 get 路径 url 上面得多个参数
     * @return
     */
    @GetMapping("/list")
    @Cacheable(value = "setmealCache",key = "#setmeal.categoryId + '_' + #setmeal.status")
    public R<List<Setmeal>> list(Setmeal setmeal){
        //输出日志调试
        log.info("移动端显示套餐数据：{}",setmeal.toString());

        //通过条件构造器进行搜索该 套餐分类id 对应得套餐
        LambdaQueryWrapper<Setmeal> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //根据当前得 套餐分类id 进行查找属于该 分类得所有 在售的套餐
        lambdaQueryWrapper.eq(setmeal.getCategoryId() != null,Setmeal::getCategoryId,setmeal.getCategoryId());
        lambdaQueryWrapper.eq(setmeal.getStatus() != null,Setmeal::getStatus,setmeal.getStatus());   //路径传过来的也是 1

        //执行命令 进行查询当前 符合条件的该套餐分类下的 所有的套餐
        List<Setmeal> list = setmealService.list(lambdaQueryWrapper);

        //返回 套餐 集合
        return R.success(list);
    }
}
